package org.feng.common;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Scope;
import org.springframework.core.annotation.Order;
import org.springframework.core.type.filter.AnnotationTypeFilter;
import org.springframework.util.CollectionUtils;

import javax.annotation.PostConstruct;
import java.util.HashSet;
import java.util.Set;

/**
 * 自定义扫描对应包下的业务Bean。<br>
 * 获取到 BeanDefinition ，注册到容器时，自定义beanName
 *
 * @version V1.0
 * @author: fengjinsong
 * @date: 2022年07月01日 15时09分
 */
@Slf4j
@Configuration
@Order(1)
public class CustomBeanDefinitionScanner implements BeanFactoryAware {

    private static BeanFactory beanFactory;

    private static final String PATH = "org.feng.businessbean";

    public static final Set<String> BEAN_NAMES = new HashSet<>();

    @Override
    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
        CustomBeanDefinitionScanner.beanFactory = beanFactory;
    }

    public static BeanFactory getBeanFactory() {
        return CustomBeanDefinitionScanner.beanFactory;
    }

    @PostConstruct
    public void registerBean() throws ClassNotFoundException {
        // 获取BeanFactory
        DefaultListableBeanFactory beanFactory = (DefaultListableBeanFactory) getBeanFactory();
        ClassPathScanningCandidateComponentProvider provider = new ClassPathScanningCandidateComponentProvider(false);
        // 增加过滤器，设置扫描BusinessBean注解对应的类
        provider.addIncludeFilter(new AnnotationTypeFilter(BeanBusiness.class));
        // 设置从CustomBeanDefinitionScanner.PATH 的包开始扫描
        Set<BeanDefinition> beanDefinitions = provider.findCandidateComponents(PATH);
        if (CollectionUtils.isEmpty(beanDefinitions)) {
            log.error("未定义带有注解 BusinessBean 的bean");
            return;
        }

        for (BeanDefinition beanDefinition : beanDefinitions) {
            final Class<?> aClass = Class.forName(beanDefinition.getBeanClassName());
            final BeanBusiness beanBusiness = Class.forName(beanDefinition.getBeanClassName()).getAnnotation(BeanBusiness.class);
            String scopeName = BeanDefinition.SCOPE_SINGLETON;
            if (Class.forName(beanDefinition.getBeanClassName()).isAnnotationPresent(Scope.class)) {
                final Scope scope = aClass.getAnnotation(Scope.class);
                if (BeanDefinition.SCOPE_PROTOTYPE.equals(scope.value())) {
                    scopeName = BeanDefinition.SCOPE_PROTOTYPE;
                }
            }
            // 后缀
            String suffix = "BeanBusiness";
            BusinessOneEnum one = beanBusiness.one();
            BusinessTwoEnum two = beanBusiness.two();
            // 拼接beanName
            String beanName = String.join("_", one.getName(), two.getName(), suffix);
            // 收集beanName，在控制台输出已经注册的所有的beanName
            BEAN_NAMES.add(beanName);
            // 指定多例还是单例
            beanDefinition.setScope(scopeName);
            // 存到Bean工厂
            beanFactory.registerBeanDefinition(beanName, beanDefinition);
        }
    }
}
